package appCache

import (
	"errors"
	"sync"
	"time"
)

//CacheRepository 缓存仓储
type CacheRepository struct {
	entityName string
	cache *Cache
}

var(
	cachePoolMap = sync.Map{}
	lock sync.Mutex
)

//GetCacheRepository 获取缓存仓储[检测过期，不检测即将到期]
func GetCacheRepository(entityName string) ICacheRepository {
	return GetCacheRepositoryAging(entityName, time.Second*30, time.Second*10, 0)
}

//GetCacheRepositoryAging 获取缓存仺储[带数据过期通知]
func GetCacheRepositoryAging(entityName string,defaultExpiration, cleanupInterval, willExpire time.Duration) ICacheRepository {
	if val, ok := cachePoolMap.Load(entityName); ok {
		return val.(ICacheRepository)
	}
	lock.Lock()
	defer lock.Unlock()

	if val, ok := cachePoolMap.Load(entityName); ok {
		return val.(ICacheRepository)
	}
	repository := &CacheRepository{
		entityName: entityName,
		cache:      NewCache(defaultExpiration, cleanupInterval, willExpire),
	}
	cachePoolMap.Store(entityName, repository)
	return repository
}

//Set 插入单个
// key 数据唯一key
// entity  结构体
// ttl     单位秒 ，0为永不到期
func (c *CacheRepository) Set(key string, entity interface{}, ttl int64) (int64, error) {
	c.cache.Set(key, entity, time.Second * time.Duration(ttl))
	return 1, nil
}

//Get 获取单个
//key 数据唯一key
func (c *CacheRepository) Get(key string)(entity interface{},err error) {
	result, ok := c.cache.Get(key)
	if !ok {
		return nil, errors.New(" key not found!")
	}
	return result, nil
}

//Remove 删除单个
// key key值
func (c *CacheRepository) Remove(keys ...string) (int64, error) {
	count := int64(0)
	for _, key := range keys {
		c.cache.Delete(key)
		count++
	}
	return count, nil
}

//OnEvicted 设置到期回调
//f 回调函数 (key,data,count,aging)
func (c *CacheRepository) OnEvicted(f func(items ...CleanItem)) {
	c.cache.OnEvicted(f)
}